// app/library/wechatPay.js
const QueryString = require('querystring');
 
// cnpm install xml2js crypto request   --save
const XmlToJs = require('xml2js').parseString;
const Crypto = require('crypto');
const Request = require('request');
 
class WechatPay {
 
  // 构造函数
  constructor(config) {
    this.config = config;
  }
 
  // 获取微信的accessToken和openid
  getAccessToken(code, callback) {
    let getAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + this.config.wxappid + "&secret=" + this.config.wxappsecret + "&code=" + code + "&grant_type=authorization_code";
    request.post({ url: getAccessTokenUrl }, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        if (40029 == body.errcode) {
          callback(error, body);
        } else {
          body = JSON.parse(body);
          callback(null, body);
        }
      } else {
        callback(error);
      }
    });
  }
 
  // 生成随机的NonceStr
  createNonceStr() {
    return Math.random().toString(36).substr(2, 15);
  };
 
  // 获取微信支付的签名
  getSign(signParams) {
    // 按 key 值的ascll 排序
    let keys = Object.keys(signParams);
    keys = keys.sort();
    let newArguments = {};
    keys.forEach(function (val, key) {
      if (signParams[val]) {
        newArguments[val] = signParams[val];
      }
    })
 
    let string = QueryString.stringify(newArguments) + '&key=' + this.config.wxpaykey;
    // 生成签名
    return Crypto.createHash('md5').update(QueryString.unescape(string), 'utf8').digest("hex").toUpperCase();
  }
 
  // 获取微信统一下单参数
  getUnifiedOrderXmlParams(obj) {
    let body = '<xml> ' +
      '<appid>' + this.config.wxappid + '</appid> ' +
      '<attach>' + obj.attach + '</attach> ' +
      '<body>' + obj.body + '</body> ' +
      '<mch_id>' + this.config.mch_id + '</mch_id> ' +
      '<nonce_str>' + obj.nonce_str + '</nonce_str> ' +
      '<notify_url>' + obj.notify_url + '</notify_url>' +
      '<openid>' + obj.openid + '</openid> ' +
      '<out_trade_no>' + obj.out_trade_no + '</out_trade_no>' +
      '<spbill_create_ip>' + obj.spbill_create_ip + '</spbill_create_ip> ' +
      '<total_fee>' + obj.total_fee + '</total_fee> ' +
      '<trade_type>' + obj.trade_type + '</trade_type> ' +
      '<sign>' + obj.sign + '</sign> ' +
      '</xml>';
    return body;
  }
 
 
  // 获取微信统一下单的接口数据
  getPrepayId(obj) {
    let that = this;
    // 生成统一下单接口参数
    let unifiedOrderParams = {
      appid: this.config.wxappid,
      attach: obj.attach,
      body: obj.body,
      mch_id: this.config.mch_id,
      nonce_str: this.createNonceStr(),
      // 微信付款后的回调地址
      notify_url: obj.notify_url,
      openid: obj.openid,
      // 订单号
      out_trade_no: obj.out_trade_no,
      spbill_create_ip: obj.spbill_create_ip,
      total_fee: obj.total_fee,
      trade_type: 'NATIVE'
      // trade_type : 'JSAPI',
      // sign : getSign(),
    };
 
    // 返回 promise 对象
    return new Promise(function (resolve, reject) {
      // 获取 sign 参数
      unifiedOrderParams.sign = that.getSign(unifiedOrderParams);
      let url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
      Request.post({ url: url, body: JSON.stringify(that.getUnifiedOrderXmlParams(unifiedOrderParams)) }, function (error, response, body) {
        if (!error && response.statusCode == 200) {
          // 微信返回的数据为xml格式， 需要转换为json数据便于使用
          XmlToJs(body, { async: true }, function (error, result) {
            if (error) {
              reject(error);
            } else {
              // let prepay_id = result.xml.prepay_id[0]; // 小程序支付返回这个
              let code_url = result.xml.code_url[0];
              resolve(code_url);
            }
          });
        } else {
          reject(body);
        }
      });
    })
  }
 
  // 微信支付的所有参数
  getWechatPayParams(obj, callback) {
    let that = this;
    let prepay_id_promise = that.getPrepayId(obj);
    prepay_id_promise.then((prepay_id) => {
 
      let wechatPayParams = {
        // 公众号名称，由商户传入
        "appId": this.config.wxappid,
        // 时间戳，自1970年以来的秒数   
        "timeStamp": parseInt(new Date().getTime() / 1000).toString(),
        // 随机字符串       
        "nonceStr": that.createNonceStr(),
        // 通过统一下单接口获取
        // "package" : "prepay_id="+prepay_id,  // 小程序支付用这个
        "code_url": prepay_id,
        // 微信签名方式
        "signType": "MD5",
      };
 
      // 微信支付签名
      wechatPayParams.paySign = that.getSign(wechatPayParams);
      callback(null, wechatPayParams);
 
    }, function (error) {
      callback(error);
    });
  }
 
  // 创建订单
  createOrder(obj, callback) {
    this.getWechatPayParams(obj, function (error, response) {
      if (error) {
        callback(error);
      } else {
        callback(null, response);
      }
    });
  }
 
}
 
module.exports = WechatPay;